package com.xhtt.modules.cfg.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhtt.common.exception.RRException;
import com.xhtt.common.exception.RRExceptionEnum;
import com.xhtt.common.utils.ExportExcel;
import com.xhtt.common.utils.PageUtils;
import com.xhtt.common.utils.Query;
import com.xhtt.modules.cfg.dao.CfgTubeInfoMapper;
import com.xhtt.modules.cfg.entity.*;
import com.xhtt.modules.cfg.model.RelateObj;
import com.xhtt.modules.cfg.schedule.TubeLog;
import com.xhtt.modules.cfg.service.*;
import com.xhtt.modules.inspection.service.IInsLabelService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * <p>
 * 硬管库 服务实现类
 * </p>
 *
 * @author feipc
 * @since 2019-02-21
 */
@Service
public class CfgTubeInfoServiceImpl extends ServiceImpl<CfgTubeInfoMapper, CfgTubeInfo> implements CfgTubeInfoService {
    @Autowired
    private CfgTubeRelateService tubeRelateService;
    @Autowired
    private CfgTubeProductService cfgTubeProductService;
    @Autowired
    private CfgTubeLogService tubeLogService;
    @Autowired
    private CfgPumpRelateService pumpRelateService;
    @Resource
    private ApplicationContext applicationContext;
    @Autowired
    private IInsLabelService insLabelService;
    @Autowired
    private CfgComprodService cfgComprodService;

    @Resource
    private ThreadPoolTaskExecutor taskExecutor;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Page<CfgTubeInfo> page = new Query<CfgTubeInfo>(params).getPage();
        List<CfgTubeInfo> list = baseMapper.queryPage(page, params);
        //连接点
//        for (CfgTubeInfo tubeInfo : list) {
//            List<CfgTubeRelate> pumpRelates = tubeRelateService.list(new LambdaQueryWrapper<CfgTubeRelate>().eq(CfgTubeRelate::getTubeId, tubeInfo.getId()));
//            List<CfgTubeRelate> guan = pumpRelates.stream().filter(pumpRelate -> pumpRelate.getType().intValue() == 1).collect(Collectors.toList());//罐
//            List<CfgTubeRelate> yingguan = pumpRelates.stream().filter(pumpRelate -> pumpRelate.getType().intValue() == 2).collect(Collectors.toList());//硬管
//            List<CfgTubeRelate> beng = pumpRelates.stream().filter(pumpRelate -> pumpRelate.getType().intValue() == 3).collect(Collectors.toList());//泵
//            List<CfgTubeRelate> matou = pumpRelates.stream().filter(pumpRelate -> pumpRelate.getType().intValue() == 4).collect(Collectors.toList());//码
//            tubeInfo.setRelateObject("待完善连接点 todo");
//        }

        page.setRecords(list);
        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void add(CfgTubeInfo cfgTubeInfo) {
        String numberNo = cfgTubeInfo.getNumberNo();
        int count = this.count(new LambdaQueryWrapper<CfgTubeInfo>().eq(CfgTubeInfo::getNumberNo, numberNo).ne(CfgTubeInfo::getStatus, -1));
        if (count > 0) {
            throw new RRException("编号已存在");
        }
        this.save(cfgTubeInfo);
        List<CfgTubeProduct> all = formTubeProduct(cfgTubeInfo);
        if (CollectionUtils.isNotEmpty(all)) {
            cfgTubeProductService.saveBatch(all);
        }
    }

    @Override
    @Transactional
    public void updateTube(CfgTubeInfo cfgTubeInfo) {
        int count = this.count(new LambdaQueryWrapper<CfgTubeInfo>().eq(CfgTubeInfo::getNumberNo, cfgTubeInfo.getNumberNo()).ne(CfgTubeInfo::getId, cfgTubeInfo.getId()).ne(CfgTubeInfo::getStatus, -1));
        if (count > 0) {
            throw new RRException("编号已存在");
        }
        CfgTubeInfo db = this.getById(cfgTubeInfo.getId());//取出对比 记日志
        this.updateById(cfgTubeInfo);
        //全删全增
        List<CfgTubeProduct> dbProducts = cfgTubeProductService.list(new LambdaQueryWrapper<CfgTubeProduct>().eq(CfgTubeProduct::getTubeId, cfgTubeInfo.getId()));//取出对比 记日志
        cfgTubeProductService.remove(new LambdaQueryWrapper<CfgTubeProduct>().eq(CfgTubeProduct::getTubeId, cfgTubeInfo.getId()));

        List<CfgTubeProduct> all = formTubeProduct(cfgTubeInfo);
        if (CollectionUtils.isNotEmpty(all)) {
            cfgTubeProductService.saveBatch(all);
        }

        taskExecutor.submit(new TubeLog(cfgTubeInfo, db, dbProducts, MDC.get("deptUser")));
    }

    @Override
    public void updateRelateObject(List<CfgTubeRelate> relates) {
        //全删全增
        Integer tubeId = relates.get(0).getTubeId();
        if (null == tubeId) {
            throw new RRException("参数有误");
        }
        tubeRelateService.remove(new LambdaQueryWrapper<CfgTubeRelate>().eq(CfgTubeRelate::getTubeId, tubeId));
        tubeRelateService.saveBatch(relates);

    }

    @Override
//    @DataSource(name = "second")
    public List<CfgTubeRelate> getRelateObject(Integer tubeId) {
        List<CfgTubeRelate> list = tubeRelateService.list(new LambdaQueryWrapper<CfgTubeRelate>().eq(CfgTubeRelate::getTubeId, tubeId));
        List<RelateObj> relateObjs;
        RelateObj ro;
        for (CfgTubeRelate re : list) {
            relateObjs = new ArrayList<>();
            ro = new RelateObj(re.getRelateId(), re.getName());
            relateObjs.add(ro);
            re.setSubRelates(relateObjs);
        }
//        XXXEvent e = new XXXEvent(ro);
//        applicationContext.publishEvent(e);
        return list;
    }

    @Override
    public void updateUsed(List<Integer> upTubeIds, Integer productId, String productName) {
        baseMapper.updateUsed(upTubeIds);
        baseMapper.updateCurProduct(upTubeIds, productId, productName);
    }

    @Override
    public void flushProduct(List<Integer> tubeIdList) {
        baseMapper.flushProduct(tubeIdList);
    }

    private List<CfgTubeProduct> formTubeProduct(CfgTubeInfo cfgTubeInfo) {
        List<CfgTubeProduct> all = new ArrayList<>();
        Integer tubeId = cfgTubeInfo.getId();
        CfgTubeProduct comProduct = cfgTubeInfo.getComTubeProduct();
        List<CfgTubeProduct> spareProducts = cfgTubeInfo.getSpareTubeProducts();
        if (null == comProduct) {
            comProduct = new CfgTubeProduct();
        }
        comProduct.setType(1);
        comProduct.setTubeId(tubeId);
        all.add(comProduct);
        if (CollectionUtils.isNotEmpty(spareProducts)) {
            spareProducts.forEach(cfgTubeProduct -> {
                cfgTubeProduct.setType(2);
                cfgTubeProduct.setTubeId(tubeId);
            });
            all.addAll(spareProducts);
        }
        return all;
    }

    @Override
    public void upload(Map<Long, Map<Integer, String>> map) {

        Set<Integer> hasErrorLines = new HashSet<>();
        Set<String> productNoExist = new HashSet<>();

        map.forEach((k, v) -> {
            boolean hasError = false;
            CfgTubeInfo cfgTubeInfo = new CfgTubeInfo();
            if (k > 2L) {
                try {
                    // 硬管编号
                    String numberNo = v.get(0);
                    if (StringUtils.isEmpty(numberNo)) {
                        hasError = true;
                    } else {
                        cfgTubeInfo.setNumberNo(numberNo);
                    }

                    // 位置一
                    String position1 = v.get(1);
                    if (StringUtils.isEmpty(position1)) {
                        hasError = true;
                    } else {
                        cfgTubeInfo.setPosition1(position1);
                    }

                    // 位置二
                    String position2 = v.get(2);
                    if (StringUtils.isEmpty(position2)) {
                        hasError = true;
                    } else {
                        cfgTubeInfo.setPosition2(position2);
                    }

                    // 常用产品
                    String common = v.get(3);
                    if (StringUtils.isNotEmpty(common)) {
                        CfgComprod cfgComprod = cfgComprodService.getByName(common);
                        if (cfgComprod == null) {
                            productNoExist.add(common);
                            hasError = true;
                        } else {
                            CfgTubeProduct cfgTubeProduct = new CfgTubeProduct();
                            cfgTubeProduct.setName(cfgComprod.getName());
                            cfgTubeProduct.setProductId(cfgComprod.getId());
                            cfgTubeInfo.setComTubeProduct(cfgTubeProduct);
                        }
                    }

                    // 备用产品
                    String spare = v.get(4);
                    if (StringUtils.isNotEmpty(spare)) {
                        CfgComprod cfgComprod = cfgComprodService.getByName(common);
                        if (cfgComprod == null) {
                            hasError = true;
                            productNoExist.add(spare);
                        } else {
                            CfgTubeProduct cfgTubeProduct = new CfgTubeProduct();
                            cfgTubeProduct.setName(cfgComprod.getName());
                            cfgTubeProduct.setProductId(cfgComprod.getId());
                            cfgTubeInfo.setComTubeProduct(cfgTubeProduct);
                            cfgTubeInfo.setSpareTubeProducts(Collections.singletonList(cfgTubeProduct));
                        }
                    }

                    // 保温
                    String insulation = v.get(5);
                    if (StringUtils.isNotEmpty(insulation)) {
                        cfgTubeInfo.setInsulation(insulation);
                    }

                    // 材质
                    String texture = v.get(6);
                    if (StringUtils.isNotEmpty(texture)) {
                        cfgTubeInfo.setTexture(texture);
                    }

                    // rfid
                    String rfid = v.get(7);
                    if (StringUtils.isEmpty(rfid)) {
                        hasError = true;
                    } else {
                        cfgTubeInfo.setRfid(rfid);
                    }
                    if (hasError) {
                        hasErrorLines.add(k.intValue());
                    } else {
                        this.add(cfgTubeInfo);
                    }
                } catch (Exception e) {
                    hasErrorLines.add(k.intValue());
                }
            }
        });
        StringBuilder stringBuilder = new StringBuilder();
        if (CollectionUtils.isNotEmpty(hasErrorLines)) {
            stringBuilder.append(insLabelService.formatUploadEx("第", hasErrorLines, "行有错误"));
        }
        if (CollectionUtils.isNotEmpty(productNoExist)) {
            stringBuilder.append(insLabelService.formatUploadEx("", productNoExist, "产品不存在"));
        }
        if (StringUtils.isNotEmpty(stringBuilder.toString())) {
            throw new RRException(stringBuilder.toString());
        }
    }

    @Override
    public void exportExcel(HttpServletResponse response, Map<String, Object> params) {
        ExportExcel exportExcel = new ExportExcel();

        params.put("limit", "65000");

        PageUtils pageUtils = queryPage(params);
        List list = pageUtils.getList();
        String fileName = "硬管数据";
        String sheetName = "sheet1";
        String[] headers = {"硬管编号", "位置1", "位置2", "目前产品", "备用产品", "材质", "保温", "RFID"};
        String[] columns = {"numberNo", "position1", "position2", "comUsedProd", "SpareUsedProd", "texture", "insulation", "rfid"};
        try {
            exportExcel.exportExcel(fileName, sheetName, headers, columns, list, response);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RRException(RRExceptionEnum.EXPORT_FAIL);
        }
    }

    @Override
    public void updateUnUsed(List<Integer> upTubeIds) {
        CfgTubeInfo tube = new CfgTubeInfo();
        tube.setUsed(0);
        this.update(tube, new LambdaQueryWrapper<CfgTubeInfo>().in(CfgTubeInfo::getId, upTubeIds));
    }

    @Override
    public PageUtils logList(Map<String, Object> params) {
        Page<CfgTubeLog> page = new Query<CfgTubeLog>(params).getPage();
        tubeLogService.page(page.setDesc("id"), new LambdaQueryWrapper<CfgTubeLog>().eq(CfgTubeLog::getTubeId, params.get("id")));
        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void updateRfid(CfgTubeInfo cfgTubeInfo) {
        CfgTubeInfo old = this.getById(cfgTubeInfo.getId());
        if (StringUtils.isEmpty(cfgTubeInfo.getRfid())) {
            this.update(new CfgTubeInfo(), new UpdateWrapper<CfgTubeInfo>().set(CfgTubeInfo.RFID, "").eq(CfgTubeInfo.ID, cfgTubeInfo.getId()));
        } else {
            this.updateById(cfgTubeInfo);
        }
        if (!ObjectUtils.nullSafeEquals(cfgTubeInfo.getRfid(), old.getRfid())) {
            String rfidInfo = old.getRfid() + " → " + cfgTubeInfo.getRfid();
            CfgTubeLog log = new CfgTubeLog();
            log.setTubeId(cfgTubeInfo.getId());
            log.setDeptUser(MDC.get("deptUser"));
            log.setRfidInfo(rfidInfo);
            log.setComProductInfo("");
            log.setSpareProductInfo("");
            tubeLogService.save(log);
        }
    }
}
